package acmath;

import java.io.Serializable;

public class Vector implements Serializable {
	private static final long serialVersionUID = 1L;

	public static Vector ZERO = new Vector(0, 0);

	private double x = 0.0d;
	private double y = 0.0d;

	public Vector(double x, double y) {
		this.x = x;
		this.y = y;
	}
	
	public Vector clone() {
		return new Vector(this.x, this.y);
	}

	public Vector add(double c) {
		return new Vector(this.x + c, this.y + c);
	}

	public Vector add(double x, double y) {
		return new Vector(this.x + x, this.y + y);
	}

	public Vector add(Vector v) {
		return new Vector(this.x + v.x, this.y + v.y);
	}

	public Vector cross(Vector v) {
		return new Vector(this.y - v.y, this.x - v.x);
	}

	public Vector divide(double c) {
		return new Vector(this.x / c, this.y / c);
	}

	public Vector divide(double x, double y) {
		return new Vector(this.x / x, this.y / y);
	}

	public Vector divide(Vector v) {
		return new Vector(this.x / v.x, this.y / v.y);
	}

	public double dot(Vector v) {
		return this.x * v.x + this.y * v.y;
	}

	@Override
	public boolean equals(Object o) {
		if (o instanceof Vector) {
			Vector v = (Vector) o;
			return x == v.x && y == v.y;
		}
		return false;
	}

	public double getX() {
		return x;
	}

	public double getY() {
		return y;
	}

	public double magnitude() {
		return Math.sqrt(this.x * this.x + this.y * this.y);
	}

	public Vector multiply(double c) {
		return new Vector(this.x * c, this.y * c);
	}

	public Vector multiply(double x, double y) {
		return new Vector(this.x * x, this.y * y);
	}

	public Vector multiply(Vector v) {
		return new Vector(this.x * v.x, this.y * v.y);
	}

	public Vector negative() {
		return this.multiply(-1);
	}

	public Vector normalize() {
		double mag = magnitude();
		if (mag != 0) {
			return new Vector(x / mag, y / mag);
		} else {
			return new Vector(x, y);
		}
	}

	public void set(int i, int j) {
		this.x = i;
		this.y = j;
	}

	public void set(double x, double y) {
		this.x = x;
		this.y = y;
	}

	public void set(Vector v) {
		x = v.x;
		y = v.y;
	}

	public void setX(double x) {
		this.x = x;
	}

	public void setY(double y) {
		this.y = y;
	}
	
	public void alterX(double x) {
		this.x += x;
	}

	public void alterY(double y) {
		this.y += y;
	}

	public Vector subtract(double c) {
		return new Vector(this.x - c, this.y - c);
	}

	public Vector subtract(double x, double y) {
		return new Vector(this.x - x, this.y - y);
	}

	public Vector subtract(Vector v) {
		return new Vector(this.x - v.x, this.y - v.y);
	}

	@Override
	public String toString() {
		return String.format("(%f,%f)", x, y);
	}

	public static Vector valueOf(float x, float y) {
		return new Vector(x, y);
	}

	public static Vector valueOf(double x, double y) {
		return new Vector(x, y);
	}
	
	public double increaseAngle(double angle) {
		double currentAngle = this.getAngle();
		double increase = angle;
		if(currentAngle + increase > Math.PI*3/2)
			currentAngle = increase - (Math.PI*3/2 - currentAngle) - Math.PI/2;
		else
			currentAngle += increase;
		return currentAngle;
	}
	
	public double decreaseAngle(double angle) {
		double currentAngle = this.getAngle();
		double decrease = angle;
		if(currentAngle - decrease < -Math.PI/2)
			currentAngle = Math.PI*3/2 - (Math.PI/2 + currentAngle) - decrease;
		else
			currentAngle -= decrease;  
		return currentAngle;
	}

	public double getAngle() {
		if (this.x == 0) {
			if (this.y > 0)
				return 3 * Math.PI / 2;
			else
				return Math.PI / 2;
		} else {
			if (this.x < 0) {
				return Math.PI + Math.atan(this.y / this.x * (-1));
			} else {
				return Math.atan(this.y * (-1) / this.x);
			}
		}
	}
}